package PushSDK

import (
	"bytes"
	"crypto/md5"
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"
	"reflect"
	"sort"
	"strconv"
	"time"
	"io/ioutil"
	//"errors"
)

func BaiduSign(method string, link string, data url.Values, sk string) (s string) {
	keys := []string{}
	s = method + link

	for k, _ := range data {
		keys = append(keys, k)
	}

	sort.Strings(keys)
	for _, v := range keys {
		s += v + "=" + data.Get(v)
	}
	s += sk
	s = url.QueryEscape(s)

	h := md5.New()
	h.Write([]byte(s))
	bts := h.Sum(nil)
	s = fmt.Sprintf("%x", bts)

	return
}

func getBaiduReq(httpMethod string, addr string, ak string, sk string, opt interface{}) (*http.Request, error) {

	data := url.Values{}
	getBaiduForm(data, opt)
	data.Add("apikey", ak)
	data.Add("sign", BaiduSign(httpMethod, addr, data, sk))

	r := bytes.NewBufferString(data.Encode())
	req, err := http.NewRequest(httpMethod, addr, r)
	if err != nil {
		return req, err
	}

	req.Header.Set("Content-Type", "application/x-www-form-urlencoded;charset=utf-8")
	req.Header.Set("User-Agent", "BCCS_SDK/3.0 GO/1.5.0 (Baidu Push Server SDK V2.0.0)")

	return req, err
}

func getBaiduForm(data url.Values, v interface{}) {
	refV := reflect.ValueOf(v)
	refT := reflect.TypeOf(v)

	if refV.Kind() == reflect.Ptr {
		refV = refV.Elem()
		refT = refT.Elem()
	}

	for i := 0; i < refV.NumField(); i++ {
		v := refV.Field(i)
		name := refT.Field(i).Tag.Get("form")
		switch v.Kind() {
		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			if v.Int() == 0 {
				break
			}
			if name != "" {
				data.Add(name, strconv.FormatInt(v.Int(), 10))
			} else {
				data.Add(refT.Field(i).Name, strconv.FormatInt(v.Int(), 10))
			}
		case reflect.String:
			if v.String() == "" {
				break
			}
			if name != "" {
				data.Add(name, v.String())
			} else {
				data.Add(refT.Field(i).Name, v.String())
			}
		default:
			break
		}
	}
	data.Add("timestamp", strconv.FormatInt(time.Now().Unix(), 10))
}

func getRespData(resp *http.Response, data interface{}) (err error) {
	dec := json.NewDecoder(resp.Body)
	for dec.More() {
		if err = dec.Decode(data); err != nil {
			fmt.Println("decode baidu response data error:" , err)
			break
		}
	}
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return
	}
	result := string(body)
	fmt.Println("baidu response result:" , result)
	return
}
